#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "pthread.h"

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWBrain.h"
#include "AWTracerBrain.h"
#include "AWThreadedBrain.h"
#include "AWNOOSBrain.h"
#include "AWNOOSLearnerBrain.h"

#include "CaseBaseUtils.h"

#include "psm.h"

#include "loader.h"





void AW_NOOSLearnerBrain::JBartering_nonstrict(FeatureTerm *problem_solution,Sort *sort,Symbol *my_name,bool test)
{
	Symbol *agent_name;
	FeatureTerm *JER;

	/* Construct the refutation sets: */ 
	{
		int pos=-1;
		List< List<FeatureTerm> > *l;
		List<FeatureTerm> *refutationset;
		FeatureTerm *justification;
		FeatureTerm *solution;

		JBartering_collected_JERs.Rewind();
		while(JBartering_collected_JERs.Iterate(JER)) {
			agent_name=JER->featureValueQuick("agent")->getSymbol();
			if (!agent_name->cmp(my_name)) {
				justification=JER->featureValueQuick("justification");
				solution=JER->featureValueQuick("solution");

				// Only consider those JERs that are wrong:
				if (!solution->equivalents(problem_solution)) {
	
					pos=JBartering_refutationsets_agent_name.Position(agent_name);
					if (pos==-1) {
						JBartering_refutationsets_agent_name.Add(new Symbol(agent_name));
						JBartering_refutationsets.Add(new List< List<FeatureTerm> >);
					} /* if */ 

					l=JBartering_refutationsets[pos];

					refutationset=new List<FeatureTerm>;
					{
						List<FeatureTerm> *cases=m_casebase->SearchFT(sort);
						FeatureTerm *c,*d,*s;

						cases->Rewind();
						while(cases->Iterate(c)) {
							d=get_description(c);
							s=get_solution(c);
							if (justification->subsumes(d) &&
								!s->equivalents(solution)) {
								refutationset->Add(new FeatureTerm(c));
							} /* if */ 
							delete s;
							delete d;
						} /* while */ 

						cases->ExtractAll();
						delete cases;
					}

					if (refutationset->EmptyP()) {
						delete refutationset;
					} else {
						l->Add(refutationset);
					} /* if */	

				} /* if */ 
			} /* if */ 

		} /* while */ 

		JBartering_collected_JERs.Delete();
	}

	/* If I've any refutation sets for any agent, send bartering offers: */ 
	{
		List< List<FeatureTerm> > *l;
		List<FeatureTerm> *l2;
		FeatureTerm *c;

		JBartering_refutationsets_agent_name.Rewind();
		JBartering_refutationsets.Rewind();
		while(JBartering_refutationsets_agent_name.Iterate(agent_name) &&
			  JBartering_refutationsets.Iterate(l)) {
			write_debug_report("[%s]:Refutation sets for agent %s:\n",my_name->get(),agent_name->get());

			// Print the refutation sets:
			l->Rewind();
			while(l->Iterate(l2)) {
				l2->Rewind();
				write_debug_report("[%s]:",my_name->get());
				while(l2->Iterate(c)) {
					write_debug_report("%s ",c->getName()->get());
				} /* while */ 
				write_debug_report("\n");
			} /* while */ 

			// Compute the best offer:
			if (l->Length()>0) {
				List<FeatureTerm> *offer;

				offer=JBartering_cases_to_offer(l,l->Length());

				write_debug_report("[%s] Offer: ",my_name->get());
				offer->Rewind();
				while(offer->Iterate(c)) {
					write_debug_report("%s ",c->getName()->get());
				} /* while */ 
				write_debug_report("\n");

				// Make offer:
				{
					FeatureTerm *f=FeatureTerm::SetFeatureTerm((Symbol *)0);
					FeatureTerm *msg,*op;
					char *str;
					int i;
					for(i=0;i<offer->Length();i++) f->addSetValue(new FeatureTerm(offer->operator [](i)));

					msg=new FeatureTerm((char *)0,m_ontology->get_sort("jbartering-cases"),1,
										"cases",f);

					str=msg->toStringNOOS(m_memory);
					op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
									   "receiver",new FeatureTerm(0,new Symbol(agent_name),m_ontology),
									   "content",new FeatureTerm(0,new Symbol(str),m_ontology));
					delete []str;
					delete msg;
					enqueue_operator(op);
					write_debug_report("[%s] offer sent to %s\n",my_name->get(),agent_name->get());
				}

				// Wait for answer:
				{
					FeatureTerm *m_content;
					AW_Message *m;
					List<FeatureTerm> *cases1;
					int n1,n2,n1f,n2f;

					wait_message();
					m=get_message();
					m_content=FeatureTerm::fromStringNOOS(m->content->get(),m_memory,m_ontology);

					cases1=m_content->featureValueQuick("cases")->set_values_quick();
					n1f=n1=cases1->Length();
					n2f=n2=offer->Length();

					if (n1==0 || n2==0) n1f=n2f=0;

					write_debug_report("[%s] Received Offer: ",my_name->get());
					cases1->Rewind();
					while(cases1->Iterate(c)) {
						write_debug_report("%s ",c->getName()->get());
					} /* while */ 
					write_debug_report("\n");
					write_debug_report("[%s] %i,%i cases exchanged(1).\n",my_name->get(),n1f,n2f);

					// Retain the first 'n3' cases of 'cases1':
					{
						int i;
						for(i=0;i<n1f;i++) retain_case(new FeatureTerm(cases1->operator [](i)));
					}


					// Remove the first 'n3' cases from the list of cases to send:
					{
						int i;
						List< List<FeatureTerm> > to_delete;
						List<FeatureTerm> *l_tmp;
						FeatureTerm *c;

						for(i=0;i<n2f;i++) {
							c=offer->operator [](i);
							l->Rewind();
							while(l->Iterate(l2)) {
								int pos;
								pos=l2->Position(c);
								if (pos!=-1) l2->DeletePosition(pos);

								if (l2->EmptyP() && !to_delete.MemberRefP(l2)) to_delete.Add(l2);
							} /* while */ 
						} /* for */ 

						while(!to_delete.EmptyP()) {
							l_tmp=to_delete.ExtractIni();
							l->DeleteElement(l_tmp);
							delete l_tmp;
						} /* while */ 
					}

					delete m_content;
					delete m;
				}

				delete offer;
			} /* if */ 
		} /* while */ 
	}
} /* AW_NOOSLearnerBrain::JBartering_nonstrict */ 


